/*
 * Copyright 2011 www.pretty-tools.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#pragma once
#include "resource.h"       // main symbols

#include "XPCOMAdapter_i.h"


#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif


// CFilePicker

class ATL_NO_VTABLE CFilePicker
    : public CComObjectRootEx<CComSingleThreadModel>
    , public CComCoClass<CFilePicker, &CLSID_FilePicker>
	, public IDispatchImpl<IFilePicker, &IID_IFilePicker, &LIBID_XPCOMAdapterLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
	, public IObjectSafetyImpl<CFilePicker, INTERFACESAFE_FOR_UNTRUSTED_CALLER>
{
public:
	CFilePicker();
	~CFilePicker();

DECLARE_REGISTRY_RESOURCEID(IDR_FILEPICKER)

BEGIN_CATEGORY_MAP(CFilePicker)
	IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
	IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
END_CATEGORY_MAP()

BEGIN_COM_MAP(CFilePicker)
	COM_INTERFACE_ENTRY(IFilePicker)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

private:
    CWindow m_wndParent;
    CString m_strTitle;
    LONG    m_nMode;
    CString m_strFilter;
    CString m_strDefaultExtension;
    CString m_strDefaultString;
    CString m_strDisplayDirectory;
    LONG    m_nFilterIndex;
	TCHAR*  m_szFileNames;
    DWORD   m_nFileOffset;

    LPCTSTR StringOrNULL(const CString &str) const 
    {
        return str.IsEmpty() ? NULL : (LPCTSTR)str;
    }

    ULONG GetFileCount(void);

	/**
	 * File iterator
	 */
	class Iterator
	{
	private:
		LPCTSTR buffer;
		LPCTSTR file_name;

	protected: friend class CFilePicker;
		Iterator(const CFilePicker &picker)
			: buffer(picker.m_szFileNames)
		{
			file_name = picker.m_szFileNames + picker.m_nFileOffset; 
		}

	public:	
		operator bool ()
		{
			return *file_name != 0;
		}

		bool operator ! ()
		{
			return !*file_name;
		}

		CString operator * () const
		{
			return GetPath();
		}

		LPCTSTR GetFileName() const
		{
			return file_name;
		}

		CString GetPath() const
		{
			return (CString)buffer + _T("\\") + file_name;
		}

        void operator ++ ()
		{
			file_name += _tcslen(file_name) + 1;
		}
	};

public:
    STDMETHOD(init)(IDispatch* parent, BSTR title, LONG mode);
    STDMETHOD(appendFilter)(BSTR title, BSTR filter);
    STDMETHOD(appendFilters)(LONG filterMask);
    STDMETHOD(show)(LONG* pRet);
    STDMETHOD(get_file)(ILocalFile** pVal);
    STDMETHOD(get_files)(ISimpleEnumerator** pVal);
    STDMETHOD(get_defaultExtension)(BSTR* pVal);
    STDMETHOD(put_defaultExtension)(BSTR newVal);
    STDMETHOD(get_defaultString)(BSTR* pVal);
    STDMETHOD(put_defaultString)(BSTR newVal);
    STDMETHOD(get_displayDirectory)(ILocalFile** pVal);
    STDMETHOD(put_displayDirectory)(ILocalFile* newVal);
    STDMETHOD(get_filterIndex)(LONG* pVal);
    STDMETHOD(put_filterIndex)(LONG newVal);
};

OBJECT_ENTRY_AUTO(__uuidof(FilePicker), CFilePicker)
